package com.espirit.hr;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.espirit.eap.manager.Department;
import com.espirit.eap.manager.DepartmentService;
import com.espirit.eap.sa.Employee;
import com.googlecode.cswish.annotation.ParamScope;
import com.googlecode.cswish.model.PageElement;
import com.googlecode.cswish.model.PageElements;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.util.bean.ModelUtil;

@Service
public class SchedualService {
	@Resource
	HrSettingService hrSettingService;
	
	@Resource
	DepartmentService departmentService;
	
	@Resource
	GenericService genericService;
	
	static final Integer DEFAULT_SCHEDUAL_DAYS = 7;
	
	static final Map<Integer, String> weekValues = new HashMap<Integer, String>();
	public SchedualService(){
		weekValues.put(1, "周一");
		weekValues.put(2, "周二");
		weekValues.put(3, "周三");
		weekValues.put(4, "周四");
		weekValues.put(5, "周五");
		weekValues.put(6, "周六");
		weekValues.put(0, "周日");
	}
	
	public Schedual _update(Schedual model,
			@ParamScope(visible=false, value="#ps")PageElements ps){
		Schedual schedual = genericService.load(model);
		Map<Integer, List<SchedualRecord>> children = new HashMap<Integer, List<SchedualRecord>>();
		for(SchedualRecord item : schedual.getChildren()){
			Employee emp = item.getEmployee();
			List<SchedualRecord> schedualRecords = children.get(emp.getId());
			if (schedualRecords == null){
				schedualRecords = new ArrayList<SchedualRecord>();
				children.put(emp.getId(), schedualRecords);
			}
			schedualRecords.add(item);
		}

		initDayLabel(children, ps);

		for(Integer empId : children.keySet()){
			List<SchedualRecord> schedualRecords = children.get(empId);
			SchedualItem schedualItem = new SchedualItem();
			Employee emp = new Employee();
			emp.setId(empId);
			emp = genericService.load(emp);
			schedualItem.setEmployee(emp);
			
			for(int i = 1; i <= schedualRecords.size(); i++){
				String scope = schedualRecords.get(i-1).getScope();
				ModelUtil.setProperty(schedualItem, "day" + i, scope); 
			}
			if (schedual.getSchedualItems() == null){
				schedual.setSchedualItems(new ArrayList<SchedualItem>());
			}
			schedual.getSchedualItems().add(schedualItem);
		}
		ModelUtil.copy(schedual, model);
		return model;
	}
	
	public void update(Schedual model){
		List<SchedualItem> schedualItems = model.getSchedualItems();
		model = genericService.load(model);
		Map<Integer, List<SchedualRecord>> children = new HashMap<Integer, List<SchedualRecord>>();
		for(SchedualRecord child : model.getChildren()){
			Employee emp = child.getEmployee();
			List<SchedualRecord> records = children.get(emp.getId());
			if (records == null){
				records = new ArrayList<SchedualRecord>();
				children.put(emp.getId(), records);
			}
			records.add(child);
		}
		
		for(SchedualItem schedualItem : schedualItems){
			Integer empId = schedualItem.getEmployee().getId();
			List<SchedualRecord> schedualRecords = children.get(empId);
			for(int i = 1 ; i <= schedualRecords.size() ; i++){
				String scope = (String) ModelUtil.getProperty(schedualItem, "day" + i);
				SchedualRecord schedualRecord = schedualRecords.get(i-1);
				schedualRecord.setScope(scope);
			}
		}
		genericService.merge(model);
	}
	
	private void initDayLabel(Map<Integer, List<SchedualRecord>> children, PageElements ps){
		String dayPrefix = "model.schedualItems.day";
		for(int i =  1 ; i <=DEFAULT_SCHEDUAL_DAYS; i++){
			PageElement pe = ps.getElement(dayPrefix + i);
			pe.setHidden(false);
		}
		for(Integer empId : children.keySet()){
			List<SchedualRecord> schedualRecords = children.get(empId);
			int sizes = schedualRecords.size();
			
			for(int i = 1; i <= sizes; i++){
				PageElement pe = ps.getElement(dayPrefix + i);
				String label = getDayLabel(schedualRecords.get(i - 1).getDutyOn());
				pe.setLabel(label);
			}
			for(int i = sizes + 1 ; i <=DEFAULT_SCHEDUAL_DAYS; i++){
				PageElement pe = ps.getElement(dayPrefix + i);
				pe.setHidden(true);
			}
			
			break;
		}
	}
	private String getDayLabel(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.setTime(date);
		int weekno = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		String prefix = new SimpleDateFormat("yyyy-M-d").format(calendar.getTime());
		String label = prefix + "(" + weekValues.get(weekno) + ")";
		return label;
	}
	
	public void generateSchedualRecord() {
		//get all schedualed department
		String[] departmentIds = hrSettingService.getSchedualDepartmentIds();
		
		if (departmentIds == null) return ;
		for(String deptId : departmentIds){
			generateSchedualRecordById(Integer.valueOf(deptId));
		}
	}
	
	private void generateSchedualRecordById(Integer deptId){
		Department department = new Department(deptId);
		String month = new SimpleDateFormat("yyyy-MM").format(new Date());
		
		Schedual schedual = new Schedual();
		schedual.setMonth(month);
		schedual.setDepartment(department);
		schedual = genericService.searchAll(schedual).getData(0);
		if (schedual != null) return ;
		
		List<Employee> employees = departmentService.getAllEmployees(deptId);
		Calendar now = Calendar.getInstance();
		now.clear();
		now.setTime(new Date());
		int lastDay = now.getActualMaximum(Calendar.DAY_OF_MONTH);
		
		for(Employee employee : employees){
			int week = 1;
			schedual = addSchedual(month, department, week);
			
			for(int i = 1; i <= lastDay; i++){
				Calendar time = Calendar.getInstance();
				time.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH) , i, 0, 0, 0);
				int weekno = time.get(Calendar.DAY_OF_WEEK) - 1; 
				
				SchedualRecord child = new SchedualRecord();
				child.setParent(schedual);
				child.setEmployee(employee);
				child.setDutyOn(time.getTime());
				genericService.add(child);
				
				if (weekno == 0 && i < lastDay){ //0 is sunday
					week ++;
					schedual = addSchedual(month, department, week);
				}
			}
		}
	}
	
	private Schedual addSchedual(String month, Department department, Integer week){
		Schedual schedual = new Schedual();
		schedual.setMonth(month);
		schedual.setDepartment(department);
		schedual.setCreated(new Date());
		schedual.setWeek(week);
		schedual = genericService.add(schedual);
		return schedual;
	}
	
}
